/*
 * @Author: Oscar Pena
 * 
 * */
package FlowGram.Application.SimulatorWindow.Simulator;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import javax.swing.JScrollPane;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import FlowGram.Application.Application;
import FlowGram.Application.Parser.FinchProgramFlow;
import FlowGram.Application.SimulatorWindow.TerrainEditor.Terrain;
import FlowGram.Application.SimulatorWindow.TerrainEditor.TerrainEditorWindow;
import FlowGram.Application.SimulatorWindow.TerrainEditor.TerrainImage;


public class SimulatorEngineWindow extends JPanel implements ActionListener, ItemListener, ChangeListener, MouseListener  {
	
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -5243686218655025561L;
	private Terrain map;
	private TerrainImage terrainImage;
	private JButton runButton = new JButton("Run");
	private JButton stepButton = new JButton("Step");
	private JSlider speedSlider = new JSlider();
	private JComboBox terrainList;
	private MessageBox messages;
	private JButton zoomInButton = new JButton("Zoom In");
	private JButton zoomOutButton = new JButton("Zoom Out");
	private FinchProgramFlow programFlow = new FinchProgramFlow();
	private SimulatorEngine simEng = new SimulatorEngine();
	private JScrollPane scrollPaneImage;
	private JScrollPane scrollPaneMessage;
	private	JSplitPane	splitPaneH;
	private	JSplitPane	splitPaneV;
	private String defaultterraindir;
	private String workspace;
	private boolean cont;
	private TerrainEditorWindow editButtons = new TerrainEditorWindow();
	private JPanel SimButtons = getSimButtons();
	private String CurrentTerrainName;
	private boolean simMode = true;
	

	public SimulatorEngineWindow(){

		super.setLayout(new BorderLayout());
		scrollPaneImage = new JScrollPane(messages, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		scrollPaneMessage = new JScrollPane(terrainImage, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		
		splitPaneV = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
		splitPaneV.setTopComponent(scrollPaneMessage );
		splitPaneV.setBottomComponent(scrollPaneImage);
		splitPaneV.setDividerLocation(500);
		
		splitPaneH = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT );
		
		splitPaneH.setLeftComponent(SimButtons);
		splitPaneH.setRightComponent(splitPaneV);
		splitPaneH.setDividerLocation(200);


		add(splitPaneH);
		terrainList.addActionListener(this);
		runButton.addActionListener(this);
		zoomInButton.addActionListener(this);
		zoomOutButton.addActionListener(this);
		stepButton.addActionListener(this);
		terrainImage.addMouseListener(this);
}
	public JPanel getSimButtons(){
		//create panel for buttons
				JPanel forButtons = new JPanel();
				terrainImage = TerrainImage.getInstance();
				forButtons.setLayout(new GridLayout(6, 1));
				forButtons.add(runButton);
				forButtons.add(stepButton);
				Dimension preferredSize = new Dimension(200, (int) super.getSize().getHeight());
				forButtons.setPreferredSize(preferredSize);
				speedSlider.setMinorTickSpacing(1);
				speedSlider.setMajorTickSpacing(1);
				speedSlider.setMaximum(5);
				speedSlider.setPaintTicks(true);
				speedSlider.setSnapToTicks(true);
				speedSlider.setPaintTrack(false);
				speedSlider.setPaintLabels(true);
				speedSlider.setToolTipText("The value is " + speedSlider.getValue());
				speedSlider.addChangeListener(this);
				forButtons.add(speedSlider);
				messages = new MessageBox();
				
				populateTerrainscombo();
				setTerrain(CurrentTerrainName);
				terrainImage.setPreferredSize(terrainImage.getSize());
				forButtons.add(terrainList);
				forButtons.add(zoomInButton);
				forButtons.add(zoomOutButton);
				Color bg = new Color(0,0,0);
				forButtons.setBackground(bg);
				return forButtons;
	}
	public void populateTerrainscombo() {
		//@Description Populate combobox with terrains in the current project folder
		//@and with default terrains
		String defaultterrainfolder = Application.getInstance().getDefaultTerrainLocation();
		defaultterraindir = defaultterrainfolder;
		workspace = Application.getInstance().getCurrentProjectPath() + File.separator + "Terrains";

		File user_dir = new File(workspace);
		terrainList = new JComboBox();
		
		String[] userTerrains = user_dir.list();
		if (userTerrains == null) {
		    // Either dir does not exist or is not a directory
		} else {
		    for (int i=0; i<userTerrains.length; i++) {
		        // Get filename of file or directory
		        String filename = userTerrains[i];
		     	System.out.println("Terrains " + userTerrains[i]);
		     	if (userTerrains[i].endsWith(".terr")){
		     		userTerrains[i] = filename.substring(0, filename.lastIndexOf('.'));
		     		terrainList.addItem(userTerrains[i]);
		     	}
		    }
		}

		File dir = new File(defaultterraindir);

		String[] TerrainNames = dir.list();
		if (TerrainNames == null) {
		    // Either dir does not exist or is not a directory
		} else {
		    for (int i=0; i<TerrainNames.length; i++) {
		        // Get filename of file or directory
		    	System.out.println("Terrains default " + TerrainNames[i]);
		        String filename = TerrainNames[i];
		    	if (TerrainNames[i].endsWith(".terr")){
		    		TerrainNames[i] = filename.substring(0, filename.lastIndexOf('.'));
		    		terrainList.addItem(TerrainNames[i]);
		    	}
		    }
		}
		terrainList.setSelectedIndex(0);
		CurrentTerrainName = terrainList.getSelectedItem().toString();
		//setTerrain(CurrentTerrainName);
	
	}
	public void setCombobox(String nameterrain){
		terrainList.setSelectedItem(nameterrain);
		this.CurrentTerrainName = nameterrain;
		setTerrain(nameterrain);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stu	
		String ap = e.getActionCommand();
		//System.out.println(ap);
		if (ap.equals("Zoom In")){
			terrainImage.setScale(1);
			terrainImage.repaint();
			messages.settext("Zoom In: " + terrainImage.getScale());
}
		if (ap.equals("Zoom Out")){
			terrainImage.setScale(0);
			terrainImage.repaint();
			messages.settext("Zoom Out: " + terrainImage.getScale());
		} 
		if (ap.equals("Run")){
			runsimulation();
		}
		if (ap.equals("Step")){
			
			if (cont == false) {
				cont = true;
				runsimulationstep();
			} else {
				cont = true;
			}
		}
		if (ap.equals("comboBoxChanged")){
			terrainImage = null;
			terrainImage = TerrainImage.getInstance();
			setTerrain(terrainList.getSelectedItem().toString());
			this.CurrentTerrainName = terrainList.getSelectedItem().toString();
			terrainImage.repaint();
		}

	}

	private void runsimulationstep() {
		//System.out.println("runsimulationstep()");

			simEng.setFinch(getCurrentMap().getFinch());
			simEng.setTerrain(map, splitPaneV, terrainImage);
			simEng.setMessageBox(messages);
			simEng.runsimulationstep(programFlow);
	}
	private void runsimulation() {
			simEng.setFinch(getCurrentMap().getFinch());
			simEng.setTerrain(map, splitPaneV, terrainImage);
			simEng.setMessageBox(messages);
			simEng.runsimulation(programFlow);
	}

	@Override
	public void itemStateChanged(ItemEvent e) {
		// TODO Auto-generated method stub
		
		
	}
	public void setTerrain(String object) {
		String input = "";
		String input2 = "";
      
		if(object.endsWith(".terr")){
			input2 = object;
		} else {
			//first check userfolder
		    if( workspace != null){
			   input = workspace + File.separator + object + ".terr";
		      }
		   input2 = defaultterraindir + File.separator + object + ".terr";
		}
		FileReader fr = null;
		try {
			fr = new FileReader(input);
		} catch (FileNotFoundException e1) {
			//e1.printStackTrace();
			try {
				fr = new FileReader(input2);
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				System.out.println("Fatal error stop");
				System.exit(1);
			}
		} 
		String terrainBuffer = "";
		try {
		    BufferedReader in = new BufferedReader(fr);
		    String str;
		    while ((str = in.readLine()) != null) {
		        terrainBuffer += str + "\n";
		    }
		    in.close();
		}catch(FileNotFoundException e){
			System.out.println(e.getMessage());
		}catch (IOException e) {
			System.out.println("Error reading file.");
		}
		messages.settext("Setting Terrain \'" + terrainList.getSelectedItem().toString() + "\'");
		generate_Terrain(terrainBuffer);	
	}
	private void generate_Terrain(String terrainBuffer) {
		// TODO Auto-generated method stub
		map = new Terrain();
		map.generate_Terrain(terrainBuffer);
		terrainImage.set_map(map);
	}


	public void settext(String t){
		messages.settext(t);
	
	}
	public void set_simulation(FinchProgramFlow flow){
		programFlow = flow;	
	}
	public void setMessage(String string) {
		// TODO Auto-generated method stub
		messages.settext(string);
	}
	@Override
	public void stateChanged(ChangeEvent arg0) {
		simEng.simcon.setDelay(speedSlider.getValue());
		speedSlider.setToolTipText("The value is " + speedSlider.getValue());
	}

	public Terrain getCurrentMap() {
		// TODO Auto-generated method stub
		return map;
	}

	public TerrainImage getTerrainImage() {
		// TODO Auto-generated method stub
		return this.terrainImage;
	}

	public MessageBox getMessageBox() {
		// TODO Auto-generated method stub
		return messages;
		
	}

	public Terrain getTerrain() {
		// TODO Auto-generated method stub
		return this.map;
	}

	public void showEditorButtons() {
		// TODO Auto-generated method stub
		simMode = false;
		editButtons.setSimWindow(this);
		splitPaneH.remove(SimButtons);
		splitPaneH.add(editButtons);
		splitPaneH.setDividerLocation(200);
		
		
	}

	public void showSinButtons() {
		// TODO Auto-generated method stub
		simMode = true;
		splitPaneH.remove(editButtons);
		splitPaneH.add(SimButtons);
		splitPaneH.setDividerLocation(200);
	}

	public String getCurrentTerrainName() {
		// TODO Auto-generated method stub
		return this.CurrentTerrainName;
	}

	@Override
	public void mouseClicked(MouseEvent arg0) {
		// TODO Auto-generated method stub
		if (simMode == false){
			System.out.println("X: " + arg0.getX() + " Y: " +arg0.getY());
			Point p = new Point(arg0.getX(), arg0.getY());
			editButtons.mouse(p);
		}
	}

	@Override
	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mousePressed(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseReleased(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

}
